/*
 * Copyright (c) 2018 Hitevision
 */

package tw.com.hitevision.whiteboard.android.widgets;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import java.util.ArrayList;
import java.util.List;

import androidx.annotation.ColorInt;
import androidx.core.content.ContextCompat;
import tw.com.hitevision.whiteboard.android.Device;
import tw.com.hitevision.whiteboard.android.Props;
import tw.com.hitevision.whiteboard.android.R;
import tw.com.hitevision.whiteboard.android.state.PenProperty;
import tw.com.hitevision.whiteboard.android.util.TouchUtils;

public class PenMenuView extends RelativeLayout implements PenHexagonPalette.HexagonLis {
    private OnChangeListener listener;

    private List<View> colors;
    private View[] sizes;

    private GestureDetector colorsGestureDetector;
    private GestureDetector sizesGestureDetector;
    private View eventView;

    @ColorInt
    private int black;
    @ColorInt
    private int white;
    @ColorInt
    private int red;
    @ColorInt
    private int yellow, pureYellow, softYellow;
    @ColorInt
    private int green, softGreen;
    @ColorInt
    private int blue, softBlue;
    @ColorInt
    private int purple;
    @ColorInt
    private int pink;
    @ColorInt
    private int vermilion;

    private PenHexagonPalette hexagonPalette;
    private ImageView colorPreview;

    public PenMenuView(Context context) {
        super(context);
        init(context);
    }

    public PenMenuView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public PenMenuView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @SuppressLint("ClickableViewAccessibility")
    private void init(Context context) {
        colorsGestureDetector = new GestureDetector(context, colorsOnGestureListener);
        sizesGestureDetector = new GestureDetector(context, sizesOnGestureListener);

        colors = new ArrayList<>();

        final Resources r = getResources();

        setBackgroundResource(R.drawable.background_highlighter_menu);

        final int paddingTop = r.getDimensionPixelSize(R.dimen.pen_menu_spacing);
        final int padding = Props.getFlavorModel().equals(Props.Flavor.Model.Wcd) ? 0 : r.getDimensionPixelSize(R.dimen.pen_menu_padding);
        setPadding(padding, paddingTop, padding, 0);

        inflate(context, R.layout.menu_pen, this);

        View color1 = findViewById(R.id.color_1);
        color1.setOnTouchListener(colorsOnTouchListener);
        View color2 = findViewById(R.id.color_2);
        color2.setOnTouchListener(colorsOnTouchListener);
        View color3 = findViewById(R.id.color_3);
        color3.setOnTouchListener(colorsOnTouchListener);
        View color4 = findViewById(R.id.color_4);
        color4.setOnTouchListener(colorsOnTouchListener);
        View color5 = findViewById(R.id.color_5);
        color5.setOnTouchListener(colorsOnTouchListener);
        View color6 = findViewById(R.id.color_6);
        color6.setOnTouchListener(colorsOnTouchListener);
        View color7 = findViewById(R.id.color_7);
        color7.setOnTouchListener(colorsOnTouchListener);
        View color8 = findViewById(R.id.color_8);
        color8.setOnTouchListener(colorsOnTouchListener);
        View color9 = findViewById(R.id.color_9);
        color9.setOnTouchListener(colorsOnTouchListener);
        View color10 = findViewById(R.id.color_10);
        color10.setOnTouchListener(colorsOnTouchListener);
        View color11 = findViewById(R.id.color_11);
        color11.setOnTouchListener(colorsOnTouchListener);

        colors.add(color1);
        colors.add(color2);
        colors.add(color3);
        colors.add(color4);
        colors.add(color5);
        colors.add(color6);
        colors.add(color7);
        colors.add(color8);
        colors.add(color9);
        colors.add(color10);
        colors.add(color11);

        colorPreview = findViewById(R.id.pen_color_preview);
        if (colorPreview != null) {
            colorPreview.setOnTouchListener(colorsOnTouchListener);
            colors.add(colorPreview);
        }

        if (Props.getFlavorModel().equals(Props.Flavor.Model.Oem)) {
            View sizeBar = findViewById(R.id.size_bar);
            sizeBar.setBackgroundColor(0); // remove background

//            color7.setVisibility(View.GONE);
        }

        black = ContextCompat.getColor(context, R.color.pen_black);
        white = ContextCompat.getColor(context, R.color.pen_white);
        red = ContextCompat.getColor(context, R.color.pen_red);
        pureYellow = ContextCompat.getColor(context, R.color.pen_pure_yellow);
        softYellow = ContextCompat.getColor(context, R.color.pen_soft_yellow);
        yellow = ContextCompat.getColor(context, R.color.pen_yellow);
        green = ContextCompat.getColor(context, R.color.pen_green);
        blue = ContextCompat.getColor(context, R.color.pen_blue);
        softGreen = ContextCompat.getColor(context, R.color.pen_soft_green);
        softBlue = ContextCompat.getColor(context, R.color.pen_soft_blue);
        purple = ContextCompat.getColor(context, R.color.pen_purple);
        pink = ContextCompat.getColor(context, R.color.pen_pink);
        vermilion = ContextCompat.getColor(context, R.color.pen_vermilion);

        View one = findViewById(R.id.one);
        one.setOnTouchListener(sizesOnTouchListener);
        View two = findViewById(R.id.two);
        two.setOnTouchListener(sizesOnTouchListener);
        View three = findViewById(R.id.three);
        three.setOnTouchListener(sizesOnTouchListener);
        View four = findViewById(R.id.four);
        four.setOnTouchListener(sizesOnTouchListener);
        View five = findViewById(R.id.five);
        five.setOnTouchListener(sizesOnTouchListener);
        sizes = new View[] {one, two, three, four, five};

        hexagonPalette = findViewById(R.id.pen_hex);
        if (hexagonPalette != null && colorPreview != null) {
            measure(0, 0);
            hexagonPalette.setHexagonLis(this);
            hexagonPalette.setHexagonPalette(r.getDimensionPixelSize(R.dimen.hex_color_width),
                    7, false,  r.obtainTypedArray(R.array.color_codes));

            @ColorInt int defaultHexPaletteColor = ContextCompat.getColor(context, R.color.hexagon_palette_default_color);
            hexagonPalette.setDefaultColor(defaultHexPaletteColor);
            colorPreview.setColorFilter(defaultHexPaletteColor);

            hexagonPalette.setVisibility(View.GONE);
        }

        ImageView paletteToggle = findViewById(R.id.pen_palette_toggle);

        if (paletteToggle != null) {
            paletteToggle.setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_POINTER_UP) {
                        if (hexagonPalette.getVisibility() == View.VISIBLE) {
                            hexagonPalette.setVisibility(View.GONE);
                        } else {
                            hexagonPalette.setVisibility(View.VISIBLE);
                        }
                    }
                    return false;
                }
            });
        }

        if (Props.getPhase() < Props.Phase.THREE && !Props.getFlavorModel().equals(Props.Flavor.Model.Oem)) {
            if (colorPreview != null) {
                colorPreview.setVisibility(View.GONE);
            }
            if (paletteToggle != null) {
                paletteToggle.setVisibility(View.GONE);
            }
        }
    }

    private void notifyPropChange(Device device, View colorView, View sizeView) {
        if (listener == null || sizeView == null || colorView == null) {
            return;
        }

        int color = 0;
        if (Props.getFlavorModel().equals(Props.Flavor.Model.Oem)) {
            switch (colorView.getId()) {
                case R.id.color_1:
                    color = white;
                    break;
                case R.id.color_2:
                    color = black;
                    break;
                case R.id.color_3:
                    color = red;
                    break;
                case R.id.color_4:
                    color = green;
                    break;
                case R.id.color_5:
                    color = blue;
                    break;
                case R.id.color_6:
                    color = pureYellow;
                    break;
                case R.id.color_7:
                    color = softBlue;
                    break;
                case R.id.color_8:
                    color = softGreen;
                    break;
                case R.id.color_9:
                    color = pink;
                    break;
                case R.id.color_10:
                    color = vermilion;
                    break;
                case R.id.color_11:
                    color = softYellow;
                    break;
                case R.id.pen_color_preview:
                    if (hexagonPalette != null) {
                        color = hexagonPalette.getSelectedColor();
                        hexagonPalette.setDefaultColor(color);
                        colorPreview.setColorFilter(color);
                    }
                    break;
            }
        } else {
            switch (colorView.getId()) {
                case R.id.color_1:
                    color = black;
                    break;
                case R.id.color_2:
                    color = white;
                    break;
                case R.id.color_3:
                    color = red;
                    break;
                case R.id.color_4:
                    color = yellow;
                    break;
                case R.id.color_5:
                    color = green;
                    break;
                case R.id.color_6:
                    color = blue;
                    break;
                case R.id.color_7:
                    color = purple;
                    break;
                case R.id.pen_color_preview:
                    if (hexagonPalette != null) {
                        color = hexagonPalette.getSelectedColor();
                        hexagonPalette.setDefaultColor(color);
                        colorPreview.setColorFilter(color);
                    }
                    break;
            }
        }

        PenProperty.Size size = null;
        switch (sizeView.getId()) {
            case R.id.one:
                size = PenProperty.Size.ONE;
                break;
            case R.id.two:
                size = PenProperty.Size.TWO;
                break;
            case R.id.three:
                size = PenProperty.Size.THREE;
                break;
            case R.id.four:
                size = PenProperty.Size.FOUR;
                break;
            case R.id.five:
                size = PenProperty.Size.FIVE;
                break;
        }

        if (size != null && color != 0) {
            listener.onSelectPenProp(device, color, size);
        }
    }

    private final OnTouchListener colorsOnTouchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            eventView = v;
            return colorsGestureDetector.onTouchEvent(event);
        }
    };

    private final GestureDetector.OnGestureListener colorsOnGestureListener
            = new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            Device device = TouchUtils.getEventDevice(getContext(), e.getActionIndex(), e);
            if (device == Device.PALM) {
                device = Device.FINGER;
            }

            for (View view : colors) {
                view.setSelected(false);
            }
            eventView.setSelected(true);

            View sizeView = null;
            for (View view : sizes) {
                if (view.isSelected()) {
                    sizeView = view;
                    break;
                }
            }

            notifyPropChange(device, eventView, sizeView);
            return true;
        }
    };

    private final OnTouchListener sizesOnTouchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            eventView = v;
            return sizesGestureDetector.onTouchEvent(event);
        }
    };

    private final GestureDetector.OnGestureListener sizesOnGestureListener
            = new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            Device device = TouchUtils.getEventDevice(getContext(), e.getActionIndex(), e);
            if (device == Device.PALM) {
                device = Device.FINGER;
            }

            for (View view : sizes) {
                view.setSelected(false);
            }
            eventView.setSelected(true);

            View colorView = null;
            for (View view : colors) {
                if (view.isSelected()) {
                    colorView = view;
                    break;
                }
            }
            notifyPropChange(device, colorView, eventView);
            return true;
        }
    };

    public void setColor(@ColorInt int color) {
        if (color == 0) {
            return;
        }

        int viewId = 0;
        if (Props.getFlavorModel().equals(Props.Flavor.Model.Oem)) {
            if (color == white) {
                viewId = R.id.color_1;
            } else if (color == black) {
                viewId = R.id.color_2;
            } else if (color == red) {
                viewId = R.id.color_3;
            } else if (color == green) {
                viewId = R.id.color_4;
            } else if (color == blue) {
                viewId = R.id.color_5;
            } else if (color == pureYellow) {
                viewId = R.id.color_6;
            } else if (color == softBlue) {
                viewId = R.id.color_7;
            } else if (color == softGreen) {
                viewId = R.id.color_8;
            } else if (color == pink) {
                viewId = R.id.color_9;
            } else if (color == vermilion) {
                viewId = R.id.color_10;
            } else if (color == softYellow) {
                viewId = R.id.color_11;
            }
        } else {
            if (color == black) {
                viewId = R.id.color_1;
            } else if (color == white) {
                viewId = R.id.color_2;
            } else if (color == red) {
                viewId = R.id.color_3;
            } else if (color == yellow) {
                viewId = R.id.color_4;
            } else if (color == green) {
                viewId = R.id.color_5;
            } else if (color == blue) {
                viewId = R.id.color_6;
            } else if (color == purple) {
                viewId = R.id.color_7;
            }
        }

        if (viewId == 0 && hexagonPalette != null && colorPreview != null) {
            @ColorInt int penColor = Color.argb(255, Color.red(color), Color.green(color), Color.blue(color));
            hexagonPalette.setDefaultColor(color);
            colorPreview.setColorFilter(penColor);
            viewId = R.id.pen_color_preview;
        }

        for (View view : colors) {
            view.setSelected(view.getId() == viewId);
        }
    }

    public void setSize(PenProperty.Size size) {
        if (size == null) {
            return;
        }

        int viewId = 0;
        switch (size) {
            case ONE:
                viewId = R.id.one;
                break;
            case TWO:
                viewId = R.id.two;
                break;
            case THREE:
                viewId = R.id.three;
                break;
            case FOUR:
                viewId = R.id.four;
                break;
            case FIVE:
                viewId = R.id.five;
                break;
        }

        for (View view : sizes) {
            view.setSelected(view.getId() == viewId);
        }
    }

    public void setProp(PenProperty prop) {
        this.setColor(prop.getColor());
        this.setSize(prop.getSize());
    }

    @Override
    public void setColorFromHexagon(MotionEvent e, int color) {
        Device device = TouchUtils.getEventDevice(getContext(), e.getActionIndex(), e);
        if (device == Device.PALM) {
            device = Device.FINGER;
        }

        for (View view : colors) {
            view.setSelected(false);
        }

        if (colorPreview != null) {
            colorPreview.setColorFilter(color);
            colorPreview.setSelected(true);
        }

        View sizeView = null;
        for (View view : sizes) {
            if (view.isSelected()) {
                sizeView = view;
                break;
            }
        }

        PenProperty.Size size = null;
        switch (sizeView.getId()) {
            case R.id.one:
                size = PenProperty.Size.ONE;
                break;
            case R.id.two:
                size = PenProperty.Size.TWO;
                break;
            case R.id.three:
                size = PenProperty.Size.THREE;
                break;
            case R.id.four:
                size = PenProperty.Size.FOUR;
                break;
            case R.id.five:
                size = PenProperty.Size.FIVE;
                break;
        }

        if (color != 0 && size != null) {
            listener.onSelectPenProp(device, color, size);
        }
    }

    public void setOnChangeListener(OnChangeListener listener) {
        this.listener = listener;
    }

    public void hideHexagonPalette() {
        if (hexagonPalette != null) {
            hexagonPalette.setVisibility(View.GONE);
        }
    }

    public interface OnChangeListener {
        void onSelectPenProp(Device device, @ColorInt int color, PenProperty.Size size);
    }
}
